package com.che.software.testato.web.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.model.SelectItem;

import org.apache.log4j.Logger;
import org.jfree.chart.ChartUtilities;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.che.software.testato.business.HierarchyManager;
import com.che.software.testato.business.IterationManager;
import com.che.software.testato.business.MatrixResultManager;
import com.che.software.testato.business.ProjectManager;
import com.che.software.testato.business.SelectionManager;
import com.che.software.testato.business.SelectiveChartManager;
import com.che.software.testato.business.SelectivePrioritizationManager;
import com.che.software.testato.business.VersionManager;
import com.che.software.testato.business.exception.IterationSearchManagerException;
import com.che.software.testato.business.exception.MatrixResultSearchManagerException;
import com.che.software.testato.business.exception.SelectionSearchManagerException;
import com.che.software.testato.domain.entity.Hierarchy;
import com.che.software.testato.domain.entity.Iteration;
import com.che.software.testato.domain.entity.MatrixResult;
import com.che.software.testato.domain.entity.Selection;
import com.che.software.testato.domain.entity.search.HierarchySearch;
import com.che.software.testato.domain.entity.search.IterationSearch;
import com.che.software.testato.domain.entity.search.MatrixResultSearch;
import com.che.software.testato.domain.entity.search.ProjectSearch;
import com.che.software.testato.domain.entity.search.SelectionSearch;
import com.che.software.testato.domain.entity.search.VersionSearch;
import com.che.software.testato.domain.enumeration.AssignmentStatus;
import com.che.software.testato.domain.enumeration.CriterionTypes;
import com.che.software.testato.domain.enumeration.SelectionTypes;
import com.che.software.testato.util.ColorUtil;
import com.che.software.testato.util.jfreechart.LineChartGraphistUtil;
import com.che.software.testato.util.jsf.faces.LocaleUtil;
import com.che.software.testato.web.controller.acontroller.AbstractController;

/**
 * Controller used to manage the selective prioritization.
 * 
 * @author Clement HELIOU (clement.heliou@che-software.com).
 * @copyright Che Software.
 * @license GNU General Public License.
 * @see AbstractController, Serializable.
 * @since August, 2011.
 * 
 *        This file is part of Testato.
 * 
 *        Testato is free software: you can redistribute it and/or modify it
 *        under the terms of the GNU General Public License as published by the
 *        Free Software Foundation, either version 3 of the License, or (at your
 *        option) any later version.
 * 
 *        Testato is distributed in the hope that it will be useful, but WITHOUT
 *        ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 *        FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
 *        for more details.
 * 
 *        You should have received a copy of the GNU General Public License
 *        along with Testato. If not, see <http://www.gnu.org/licenses/>.
 * 
 *        Testato's logo is a creation of Arrioch
 *        (http://arrioch.deviantart.com/) and it's distributed under the terms
 *        of the Creative Commons License.
 */
@Component("selectivePrioritizationController")
@ManagedBean(name = "selectivePrioritizationController")
@Scope("session")
@SessionScoped
public class SelectivePrioritizationController extends AbstractController implements Serializable {

	/**
	 * Constants.
	 */
	private static final Logger LOGGER = Logger.getLogger(SelectivePrioritizationController.class);
	private static final long serialVersionUID = -5921864431562266368L;

	/**
	 * Members.
	 */
	private Boolean selectivePrioritizationCompleted;
	private Double reductionRate;
	private Hierarchy currentHierarchy;
	@Autowired
	private transient HierarchyManager hierarchyManager;
	private Integer currentIteration;
	private Iteration costAssignment, fitAssignment, riskAssignment, valueAssignment;
	@Autowired
	private transient IterationManager iterationManager;
	private List<Iteration> currentIterationAssignments;
	private List<MatrixResult> costResults, fitResults, riskResults, selectedCostResults, selectedFitResults, selectedRiskResults, selectedValueResults, valueResults;
	private List<Selection> selectionsTable;
	private List<SelectItem> selectionTypes;
	@Autowired
	private transient MatrixResultManager matrixResultManager;
	@Autowired
	private transient ProjectManager projectManager;
	@Autowired
	private transient SelectionManager selectionManager;
	private SelectionTypes selectedSelectionType;
	@Autowired
	private transient SelectiveChartManager selectiveChartManager;
	@Autowired
	private transient SelectivePrioritizationManager selectivePrioritizationManager;
	private StreamedContent costValueChart, fitRiskChart, fullCostValueChart, fullFitRiskChart;
	@Autowired
	private transient VersionManager versionManager;

	/**
	 * Getter for the reduction rate performed by the selective prioritization.
	 * 
	 * @author Clement HELIOU (clement.heliou@che-software.com).
	 * @return the resulting reduction rate.
	 * @since August, 2011.
	 */
	public Double getReductionRate() {
		if (null == reductionRate) {
			LOGGER.debug("getReductionRate(): initialization.");
			reductionRate = 100.0 - (((double) getSelectedCostResults().size() / (getSelectedCostResults().size() + getCostResults().size())) * 100.0);
		}
		return reductionRate;
	}

	/**
	 * Method called to redirect the user to the selective prioritization page.
	 * 
	 * @author Clement HELIOU (clement.heliou@che-software.com).
	 * @return the url to follow.
	 * @since August, 2011.
	 */
	public String onSelectivePrioritization() {
		LOGGER.debug("onSelectivePrioritization(" + currentIteration + ").");
		init();
		return "selectivePrioritization.xhtml?faces-redirect=true";
	}

	/**
	 * Method called to perform the selective prioritization.
	 * 
	 * @author Clement HELIOU (clement.heliou@che-software.com).
	 * @return null because none redirection is necessary.
	 * @since August, 2011.
	 */
	public String onSelectPrioritizationType() {
		LOGGER.debug("onSelectPrioritizationType().");
		try {
			selectivePrioritizationManager.prioritize(getCurrentIteration(), selectedSelectionType, getSelectedCostResults(), getSelectedValueResults(), getSelectedFitResults(), getSelectedRiskResults());
			init();
		} catch (Exception e) {
			LOGGER.error("Error during the selective prioritization.", e);
		}
		return null;
	}

	/**
	 * Getter for the private field value currentHierarchy.
	 * 
	 * @return the currentHierarchy field value.
	 */
	public Hierarchy getCurrentHierarchy() {
		if (null == currentHierarchy && null != getCurrentIteration()) {
			LOGGER.debug("getCurrentHierarchy(): initialization.");
			HierarchySearch searchBean = new HierarchySearch();
			searchBean.setIterationId(getCurrentIteration());
			try {
				currentHierarchy = hierarchyManager.searchHierarchy(searchBean).get(0);
				currentHierarchy.setVersion(versionManager.searchVersion(new VersionSearch(currentHierarchy.getVersionId())).get(0));
				currentHierarchy.setProject(projectManager.searchProject(new ProjectSearch(currentHierarchy.getVersion().getProjectId())).get(0));
			}
			catch (Exception e) {
				LOGGER.error("Error during the current hierarchy recovery.");
			}
		}
		return currentHierarchy;
	}

	/**
	 * Method used to initialize the different fields to trigger the data loading.
	 * 
	 * @author Clement HELIOU (clement.heliou@che-software.com).
	 * @since August, 2011.
	 */
	private void init() {
		costResults = null; // To trigger the data loading.
		costValueChart = null;
		costAssignment = null;
		currentHierarchy = null;
		currentIterationAssignments = null;
		fitAssignment = null;
		fitRiskChart = null;
		fitResults = null;
		fullCostValueChart = null;
		fullFitRiskChart = null;
		reductionRate = null;
		riskAssignment = null;
		riskResults = null;
		selectedCostResults = null;
		selectedFitResults = null;
		selectedRiskResults = null;
		selectedValueResults = null;
		selectivePrioritizationCompleted = null;
		valueAssignment = null;
		valueResults = null;
	}

	/**
	 * Setting a value to the currentHierarchy field.
	 * 
	 * @param currentHierarchy the value to set.
	 */
	public void setCurrentHierarchy(Hierarchy currentHierarchy) {
		this.currentHierarchy = currentHierarchy;
	}

	/**
	 * Getter for the private field value selectionManager.
	 * 
	 * @return the selectionManager field value.
	 */
	public SelectionManager getSelectionManager() {
		return selectionManager;
	}

	/**
	 * Setting a value to the selectionManager field.
	 * 
	 * @param selectionManager the value to set.
	 */
	public void setSelectionManager(SelectionManager selectionManager) {
		this.selectionManager = selectionManager;
	}

	/**
	 * Getter for the private field value selectionsTable.
	 * 
	 * @return the selectionsTable field value.
	 */
	public List<Selection> getSelectionsTable() {
		if (null == selectionsTable) {
			LOGGER.debug("getSelectionsTable().");
			try {
				selectionsTable = selectionManager.searchSelection(new SelectionSearch());
			} catch (SelectionSearchManagerException e) {
				LOGGER.error("Error during the selective reference table.", e);
			}
		}
		return selectionsTable;
	}

	/**
	 * Setting a value to the selectionsTable field.
	 * 
	 * @param selectionsTable the value to set.
	 */
	public void setSelectionsTable(List<Selection> selectionsTable) {
		this.selectionsTable = selectionsTable;
	}

	/**
	 * Getter for the private field value selectionTypes.
	 * 
	 * @return the selectionTypes field value.
	 */
	public List<SelectItem> getSelectionTypes() {
		if (null == selectionTypes) {
			LOGGER.debug("getSelectionTypes(): initialization.");
			List<SelectItem> items = new ArrayList<SelectItem>();
			for (SelectionTypes selectionType : SelectionTypes.values()) {
				items.add(new SelectItem(selectionType, LocaleUtil.getSelectionTranslation(selectionType)));
			}
			selectionTypes = items;
		}
		return selectionTypes;
	}

	/**
	 * Setting a value to the selectionTypes field.
	 * 
	 * @param selectionTypes the value to set.
	 */
	public void setSelectionTypes(List<SelectItem> selectionTypes) {
		this.selectionTypes = selectionTypes;
	}

	/**
	 * Getter for the private field value costValueChart.
	 * 
	 * @return the costValueChart field value.
	 */
	public StreamedContent getCostValueChart() {
		if (null == costValueChart) {
			LOGGER.debug("getCostValueChart(): intialization.");
			File file = new File("costValueChart");
			try {
				ChartUtilities.saveChartAsPNG(file, LineChartGraphistUtil.getColorizedChartFromChart(selectiveChartManager.createSelectiveChart(getSelectedCostResults(), getSelectedValueResults(), LocaleUtil.getResourceBundleStringByName(LocaleUtil.COST_CRITERION_NAME) + "/" + LocaleUtil.getResourceBundleStringByName(LocaleUtil.VALUE_CRITERION_NAME), LocaleUtil.getResourceBundleStringByName(LocaleUtil.COST_CRITERION_NAME), LocaleUtil.getResourceBundleStringByName(LocaleUtil.VALUE_CRITERION_NAME), getCostResults(), getValueResults()), LineChartGraphistUtil.getMaxAbscissaValue(getSelectedCostResults(), getCostResults()), getSelectedCostResults(), getSelectedValueResults(), getCostResults(), getValueResults()), ColorUtil.MICRO_SIZE.width, ColorUtil.MICRO_SIZE.height);
				costValueChart = new DefaultStreamedContent(new FileInputStream(file));
			} catch (IOException e) {
				LOGGER.error("Error during the cost-value chart recovery.", e);
			}
		}
		return costValueChart;
	}

	/**
	 * Setting a value to the costValueChart field.
	 * 
	 * @param costValueChart the value to set.
	 */
	public void setCostValueChart(StreamedContent costValueChart) {
		this.costValueChart = costValueChart;
	}

	/**
	 * Getter for the private field value fitRiskChart.
	 * 
	 * @return the fitRiskChart field value.
	 */
	public StreamedContent getFitRiskChart() {
		if (null == fitRiskChart) {
			LOGGER.debug("getFitRiskChart(): intialization.");
			File file = new File("fitRiskChart");
			try {
				ChartUtilities.saveChartAsPNG(file, LineChartGraphistUtil.getColorizedChartFromChart(selectiveChartManager.createSelectiveChart(getSelectedFitResults(), getSelectedRiskResults(), LocaleUtil.getResourceBundleStringByName(LocaleUtil.FIT_CRITERION_NAME) + "/" + LocaleUtil.getResourceBundleStringByName(LocaleUtil.RISK_CRITERION_NAME), LocaleUtil.getResourceBundleStringByName(LocaleUtil.FIT_CRITERION_NAME), LocaleUtil.getResourceBundleStringByName(LocaleUtil.RISK_CRITERION_NAME), getFitResults(), getRiskResults()), LineChartGraphistUtil.getMaxAbscissaValue(getSelectedFitResults(), getFitResults()), getSelectedFitResults(), getSelectedRiskResults(), getFitResults(), getRiskResults()), ColorUtil.MICRO_SIZE.width, ColorUtil.MICRO_SIZE.height);
				fitRiskChart = new DefaultStreamedContent(new FileInputStream(file));
			} catch (IOException e) {
				LOGGER.error("Error during the fit-risk chart recovery.", e);
			}
		}
		return fitRiskChart;
	}

	/**
	 * Setting a value to the fitRiskChart field.
	 * 
	 * @param fitRiskChart the value to set.
	 */
	public void setFitRiskChart(StreamedContent fitRiskChart) {
		this.fitRiskChart = fitRiskChart;
	}

	/**
	 * Getter for the private field value fullCostValueChart.
	 * 
	 * @return the fullCostValueChart field value.
	 */
	public StreamedContent getFullCostValueChart() {
		if (null == fullCostValueChart) {
			LOGGER.debug("getFullCostValueChart(): intialization.");
			File file = new File("fullCostValueChart");
			try {
				ChartUtilities.saveChartAsPNG(file, LineChartGraphistUtil.getColorizedChartFromChart(selectiveChartManager.createSelectiveChart(getSelectedCostResults(), getSelectedValueResults(), LocaleUtil.getResourceBundleStringByName(LocaleUtil.COST_CRITERION_NAME) + "/" + LocaleUtil.getResourceBundleStringByName(LocaleUtil.VALUE_CRITERION_NAME), LocaleUtil.getResourceBundleStringByName(LocaleUtil.COST_CRITERION_NAME), LocaleUtil.getResourceBundleStringByName(LocaleUtil.VALUE_CRITERION_NAME), getCostResults(), getValueResults()), LineChartGraphistUtil.getMaxAbscissaValue(getSelectedCostResults(), getCostResults()), getSelectedCostResults(), getSelectedValueResults(), getCostResults(), getValueResults()), ColorUtil.FULL_SCREEN_SIZE.width, ColorUtil.FULL_SCREEN_SIZE.height);
				fullCostValueChart = new DefaultStreamedContent(new FileInputStream(file));
			} catch (IOException e) {
				LOGGER.error("Error during the full cost-value chart recovery.", e);
			}
		}
		return fullCostValueChart;
	}

	/**
	 * Setting a value to the fullCostValueChart field.
	 * 
	 * @param fullCostValueChart the value to set.
	 */
	public void setFullCostValueChart(StreamedContent fullCostValueChart) {
		this.fullCostValueChart = fullCostValueChart;
	}

	/**
	 * Getter for the private field value fullFitRiskChart.
	 * 
	 * @return the fullFitRiskChart field value.
	 */
	public StreamedContent getFullFitRiskChart() {
		if (null == fullFitRiskChart) {
			LOGGER.debug("getFullFitRiskChart(): intialization.");
			File file = new File("fullFitRiskChart");
			try {
				ChartUtilities.saveChartAsPNG(file, LineChartGraphistUtil.getColorizedChartFromChart(selectiveChartManager.createSelectiveChart(getSelectedFitResults(), getSelectedRiskResults(), LocaleUtil.getResourceBundleStringByName(LocaleUtil.FIT_CRITERION_NAME) + "/" + LocaleUtil.getResourceBundleStringByName(LocaleUtil.RISK_CRITERION_NAME), LocaleUtil.getResourceBundleStringByName(LocaleUtil.FIT_CRITERION_NAME), LocaleUtil.getResourceBundleStringByName(LocaleUtil.RISK_CRITERION_NAME), getFitResults(), getRiskResults()), LineChartGraphistUtil.getMaxAbscissaValue(getSelectedFitResults(), getFitResults()), getSelectedFitResults(), getSelectedRiskResults(), getFitResults(), getRiskResults()), ColorUtil.FULL_SCREEN_SIZE.width, ColorUtil.FULL_SCREEN_SIZE.height);
				fullFitRiskChart = new DefaultStreamedContent(new FileInputStream(file));
			} catch (IOException e) {
				LOGGER.error("Error during the full fit-risk chart recovery.", e);
			}
		}
		return fullFitRiskChart;
	}

	/**
	 * Setting a value to the fullFitRiskChart field.
	 * 
	 * @param fullFitRiskChart the value to set.
	 */
	public void setFullFitRiskChart(StreamedContent fullFitRiskChart) {
		this.fullFitRiskChart = fullFitRiskChart;
	}

	/**
	 * Getter for the private field value selectiveChartManager.
	 * 
	 * @return the selectiveChartManager field value.
	 */
	public SelectiveChartManager getSelectiveChartManager() {
		return selectiveChartManager;
	}

	/**
	 * Setting a value to the selectiveChartManager field.
	 * 
	 * @param selectiveChartManager the value to set.
	 */
	public void setSelectiveChartManager(SelectiveChartManager selectiveChartManager) {
		this.selectiveChartManager = selectiveChartManager;
	}

	/**
	 * Getter for the private field value currentIterationAssignments.
	 * 
	 * @return the currentIterationAssignments field value.
	 */
	public List<Iteration> getCurrentIterationAssignments() {
		if (null == currentIterationAssignments) {
			LOGGER.debug("getCurrentIterationAssignments(): initialization.");
			IterationSearch searchBean = new IterationSearch();
			searchBean.setAnalyticalStatus(AssignmentStatus.ENDED);
			searchBean.setSelectiveStatusNull(true);
			try {
				searchBean.setIterationId(getCurrentIteration());
				List<Iteration> iterationAssignments = iterationManager.searchIteration(searchBean);
				currentIterationAssignments = iterationAssignments;
			} catch (Exception e) {
				LOGGER.error("Error during an iteration recovery.", e);
			}
		}
		return currentIterationAssignments;
	}

	/**
	 * Setting a value to the currentIterationAssignments field.
	 * 
	 * @param currentIterationAssignments the value to set.
	 */
	public void setCurrentIterationAssignments(List<Iteration> currentIterationAssignments) {
		this.currentIterationAssignments = currentIterationAssignments;
	}

	/**
	 * Getter for the private field value iterationManager.
	 * 
	 * @return the iterationManager field value.
	 */
	public IterationManager getIterationManager() {
		return iterationManager;
	}

	/**
	 * Setting a value to the iterationManager field.
	 * 
	 * @param iterationManager the value to set.
	 */
	public void setIterationManager(IterationManager iterationManager) {
		this.iterationManager = iterationManager;
	}

	/**
	 * Getter for the private field value costResults.
	 * 
	 * @return the costResults field value.
	 */
	public List<MatrixResult> getCostResults() {
		if (null == costResults) {
			LOGGER.debug("getCostResults(): initialization.");
			try {
				MatrixResultSearch searchBean = new MatrixResultSearch(getCostAssignment().getIterationAssignmentId());
				searchBean.setSelected(false);
				costResults = matrixResultManager.searchMatrixResult(searchBean);
			} catch (MatrixResultSearchManagerException e) {
				LOGGER.error("Error during the cost results recovery.", e);
			}
		}
		return costResults;
	}

	/**
	 * Setting a value to the costResults field.
	 * 
	 * @param costResults the value to set.
	 */
	public void setCostResults(List<MatrixResult> costResults) {
		this.costResults = costResults;
	}

	/**
	 * Getter for the private field value fitResults.
	 * 
	 * @return the fitResults field value.
	 */
	public List<MatrixResult> getFitResults() {
		if (null == fitResults) {
			LOGGER.debug("getFitResults(): initialization.");
			try {
				MatrixResultSearch searchBean = new MatrixResultSearch(getFitAssignment().getIterationAssignmentId());
				searchBean.setSelected(false);
				fitResults = matrixResultManager.searchMatrixResult(searchBean);
			} catch (MatrixResultSearchManagerException e) {
				LOGGER.error("Error during the fit results recovery.", e);
			}
		}
		return fitResults;
	}

	/**
	 * Setting a value to the fitResults field.
	 * 
	 * @param fitResults the value to set.
	 */
	public void setFitResults(List<MatrixResult> fitResults) {
		this.fitResults = fitResults;
	}

	/**
	 * Getter for the private field value riskResults.
	 * 
	 * @return the riskResults field value.
	 */
	public List<MatrixResult> getRiskResults() {
		if (null == riskResults) {
			LOGGER.debug("getRiskResults(): initialization.");
			try {
				MatrixResultSearch searchBean = new MatrixResultSearch(getRiskAssignment().getIterationAssignmentId());
				searchBean.setSelected(false);
				riskResults = matrixResultManager.searchMatrixResult(searchBean);
			} catch (MatrixResultSearchManagerException e) {
				LOGGER.error("Error during the fit results recovery.", e);
			}
		}
		return riskResults;
	}

	/**
	 * Setting a value to the riskResults field.
	 * 
	 * @param riskResults the value to set.
	 */
	public void setRiskResults(List<MatrixResult> riskResults) {
		this.riskResults = riskResults;
	}

	/**
	 * Getter for the private field value selectedCostResults.
	 * 
	 * @return the selectedCostResults field value.
	 */
	public List<MatrixResult> getSelectedCostResults() {
		if (null == selectedCostResults) {
			LOGGER.debug("getSelectedCostResults(): initialization.");
			try {
				MatrixResultSearch searchBean = new MatrixResultSearch(getCostAssignment().getIterationAssignmentId());
				searchBean.setSelected(true);
				selectedCostResults = matrixResultManager.searchMatrixResult(searchBean);
			} catch (MatrixResultSearchManagerException e) {
				LOGGER.error("Error during the fit results recovery.", e);
			}
		}
		return selectedCostResults;
	}

	/**
	 * Setting a value to the selectedCostResults field.
	 * 
	 * @param selectedCostResults the value to set.
	 */
	public void setSelectedCostResults(List<MatrixResult> selectedCostResults) {
		this.selectedCostResults = selectedCostResults;
	}

	/**
	 * Getter for the private field value selectedFitResults.
	 * 
	 * @return the selectedFitResults field value.
	 */
	public List<MatrixResult> getSelectedFitResults() {
		if (null == selectedFitResults) {
			LOGGER.debug("getSelectedFitResults(): initialization.");
			try {
				MatrixResultSearch searchBean = new MatrixResultSearch(getFitAssignment().getIterationAssignmentId());
				searchBean.setSelected(true);
				selectedFitResults = matrixResultManager.searchMatrixResult(searchBean);
			} catch (MatrixResultSearchManagerException e) {
				LOGGER.error("Error during the fit results recovery.", e);
			}
		}
		return selectedFitResults;
	}

	/**
	 * Setting a value to the selectedFitResults field.
	 * 
	 * @param selectedFitResults the value to set.
	 */
	public void setSelectedFitResults(List<MatrixResult> selectedFitResults) {
		this.selectedFitResults = selectedFitResults;
	}

	/**
	 * Getter for the private field value selectedRiskResults.
	 * 
	 * @return the selectedRiskResults field value.
	 */
	public List<MatrixResult> getSelectedRiskResults() {
		if (null == selectedRiskResults) {
			LOGGER.debug("getSelectedRiskResults(): initialization.");
			try {
				MatrixResultSearch searchBean = new MatrixResultSearch(getRiskAssignment().getIterationAssignmentId());
				searchBean.setSelected(true);
				selectedRiskResults = matrixResultManager.searchMatrixResult(searchBean);
			} catch (MatrixResultSearchManagerException e) {
				LOGGER.error("Error during the fit results recovery.", e);
			}
		}
		return selectedRiskResults;
	}

	/**
	 * Setting a value to the selectedRiskResults field.
	 * 
	 * @param selectedRiskResults the value to set.
	 */
	public void setSelectedRiskResults(List<MatrixResult> selectedRiskResults) {
		this.selectedRiskResults = selectedRiskResults;
	}

	/**
	 * Getter for the private field value selectedValueResults.
	 * 
	 * @return the selectedValueResults field value.
	 */
	public List<MatrixResult> getSelectedValueResults() {
		if (null == selectedValueResults) {
			LOGGER.debug("getSelectedValueResults(): initialization.");
			try {
				MatrixResultSearch searchBean = new MatrixResultSearch(getValueAssignment().getIterationAssignmentId());
				searchBean.setSelected(true);
				selectedValueResults = matrixResultManager.searchMatrixResult(searchBean);
			} catch (MatrixResultSearchManagerException e) {
				LOGGER.error("Error during the fit results recovery.", e);
			}
		}
		return selectedValueResults;
	}

	/**
	 * Setting a value to the selectedValueResults field.
	 * 
	 * @param selectedValueResults the value to set.
	 */
	public void setSelectedValueResults(List<MatrixResult> selectedValueResults) {
		this.selectedValueResults = selectedValueResults;
	}

	/**
	 * Getter for the private field value valueResults.
	 * 
	 * @return the valueResults field value.
	 */
	public List<MatrixResult> getValueResults() {
		if (null == valueResults) {
			LOGGER.debug("getValueResults(): initialization.");
			try {
				MatrixResultSearch searchBean = new MatrixResultSearch(getValueAssignment().getIterationAssignmentId());
				searchBean.setSelected(false);
				valueResults = matrixResultManager.searchMatrixResult(searchBean);
			} catch (MatrixResultSearchManagerException e) {
				LOGGER.error("Error during the fit results recovery.", e);
			}
		}
		return valueResults;
	}

	/**
	 * Setting a value to the valueResults field.
	 * 
	 * @param valueResults the value to set.
	 */
	public void setValueResults(List<MatrixResult> valueResults) {
		this.valueResults = valueResults;
	}

	/**
	 * Getter for the private field value matrixResultManager.
	 * 
	 * @return the matrixResultManager field value.
	 */
	public MatrixResultManager getMatrixResultManager() {
		return matrixResultManager;
	}

	/**
	 * Setting a value to the matrixResultManager field.
	 * 
	 * @param matrixResultManager the value to set.
	 */
	public void setMatrixResultManager(MatrixResultManager matrixResultManager) {
		this.matrixResultManager = matrixResultManager;
	}

	/**
	 * Getter for the private field value costAssignment.
	 * 
	 * @return the costAssignment field value.
	 */
	public Iteration getCostAssignment() {
		if (null == costAssignment) {
			LOGGER.debug("getCostAssignment(): initialization.");
			for (Iteration iteration : getCurrentIterationAssignments()) {
				if (iteration.getCriterionType().equals(CriterionTypes.COST)) {
					costAssignment = iteration;
					break;
				}
			}
		}
		return costAssignment;
	}

	/**
	 * Setting a value to the costAssignment field.
	 * 
	 * @param costAssignment the value to set.
	 */
	public void setCostAssignment(Iteration costAssignment) {
		this.costAssignment = costAssignment;
	}

	/**
	 * Getter for the private field value fitAssignment.
	 * 
	 * @return the fitAssignment field value.
	 */
	public Iteration getFitAssignment() {
		if (null == fitAssignment) {
			LOGGER.debug("getFitAssignment(): initialization.");
			for (Iteration iteration : getCurrentIterationAssignments()) {
				if (iteration.getCriterionType().equals(CriterionTypes.FIT)) {
					fitAssignment = iteration;
					break;
				}
			}
		}
		return fitAssignment;
	}

	/**
	 * Setting a value to the fitAssignment field.
	 * 
	 * @param fitAssignment the value to set.
	 */
	public void setFitAssignment(Iteration fitAssignment) {
		this.fitAssignment = fitAssignment;
	}

	/**
	 * Getter for the private field value riskAssignment.
	 * 
	 * @return the riskAssignment field value.
	 */
	public Iteration getRiskAssignment() {
		if (null == riskAssignment) {
			LOGGER.debug("getRiskAssignment(): initialization.");
			for (Iteration iteration : getCurrentIterationAssignments()) {
				if (iteration.getCriterionType().equals(CriterionTypes.RISK)) {
					riskAssignment = iteration;
					break;
				}
			}
		}
		return riskAssignment;
	}

	/**
	 * Setting a value to the riskAssignment field.
	 * 
	 * @param riskAssignment the value to set.
	 */
	public void setRiskAssignment(Iteration riskAssignment) {
		this.riskAssignment = riskAssignment;
	}

	/**
	 * Getter for the private field value valueAssignment.
	 * 
	 * @return the valueAssignment field value.
	 */
	public Iteration getValueAssignment() {
		if (null == valueAssignment) {
			LOGGER.debug("getValueAssignment(): initialization.");
			for (Iteration iteration : getCurrentIterationAssignments()) {
				if (iteration.getCriterionType().equals(CriterionTypes.VALUE)) {
					valueAssignment = iteration;
					break;
				}
			}
		}
		return valueAssignment;
	}

	/**
	 * Setting a value to the valueAssignment field.
	 * 
	 * @param valueAssignment the value to set.
	 */
	public void setValueAssignment(Iteration valueAssignment) {
		this.valueAssignment = valueAssignment;
	}

	/**
	 * Getter for the private field value selectivePrioritizationManager.
	 * 
	 * @return the selectivePrioritizationManager field value.
	 */
	public SelectivePrioritizationManager getSelectivePrioritizationManager() {
		return selectivePrioritizationManager;
	}

	/**
	 * Setting a value to the selectivePrioritizationManager field.
	 * 
	 * @param selectivePrioritizationManager the value to set.
	 */
	public void setSelectivePrioritizationManager(SelectivePrioritizationManager selectivePrioritizationManager) {
		this.selectivePrioritizationManager = selectivePrioritizationManager;
	}

	/**
	 * Getter for the private field value selectedSelectionType.
	 * 
	 * @return the selectedSelectionType field value.
	 */
	public SelectionTypes getSelectedSelectionType() {
		return selectedSelectionType;
	}

	/**
	 * Setting a value to the selectedSelectionType field.
	 * 
	 * @param selectedSelectionType the value to set.
	 */
	public void setSelectedSelectionType(SelectionTypes selectedSelectionType) {
		this.selectedSelectionType = selectedSelectionType;
	}

	/**
	 * Getter for the private field value currentIteration.
	 * 
	 * @return the currentIteration field value.
	 */
	public Integer getCurrentIteration() {
		if (null == currentIteration) {
			LOGGER.debug("getCurrentIteration(): intialization.");
			try {
				currentIteration = iterationManager.getCurrentIterationFromHierarchy(currentHierarchy.getHierarchyId());
			} catch (IterationSearchManagerException e) {
				LOGGER.error("Error during the current iteration recovery.", e);
			}
		}
		return currentIteration;
	}

	/**
	 * Setting a value to the currentIteration field.
	 * 
	 * @param currentIteration the value to set.
	 */
	public void setCurrentIteration(Integer currentIteration) {
		this.currentIteration = currentIteration;
	}

	/**
	 * Getter for the private field value selectivePrioritizationCompleted.
	 * 
	 * @return the selectivePrioritizationCompleted field value.
	 */
	public Boolean getSelectivePrioritizationCompleted() {
		if (null == selectivePrioritizationCompleted) {
			LOGGER.debug("getSelectivePrioritizationCompleted():initialization.");
			IterationSearch searchBean = new IterationSearch();
			searchBean.setSelectiveStatus(AssignmentStatus.ENDED);
			searchBean.setIterationId(getCurrentIteration());
			try {
				List<Iteration> iterations = iterationManager.searchIteration(searchBean);
				selectivePrioritizationCompleted = null != iterations && !iterations.isEmpty();
			} catch (IterationSearchManagerException e) {
				LOGGER.error("Error during the completed iteration status checking.", e);
			}
		}
		return selectivePrioritizationCompleted;
	}

	/**
	 * Setting a value to the selectivePrioritizationCompleted field.
	 * 
	 * @param selectivePrioritizationCompleted the value to set.
	 */
	public void setSelectivePrioritizationCompleted(Boolean selectivePrioritizationCompleted) {
		this.selectivePrioritizationCompleted = selectivePrioritizationCompleted;
	}

	/**
	 * Setting a value to the reductionRate field.
	 * 
	 * @param reductionRate the value to set.
	 */
	public void setReductionRate(Double reductionRate) {
		this.reductionRate = reductionRate;
	}

	/**
	 * Getter for the private field value hierarchyManager.
	 * 
	 * @return the hierarchyManager field value.
	 */
	public HierarchyManager getHierarchyManager() {
		return hierarchyManager;
	}

	/**
	 * Setting a value to the hierarchyManager field.
	 * 
	 * @param hierarchyManager the value to set.
	 */
	public void setHierarchyManager(HierarchyManager hierarchyManager) {
		this.hierarchyManager = hierarchyManager;
	}

	/**
	 * Methode d'acces au champ projectManager.
	 * 
	 * @return la valeur du champ projectManager.
	 */
	public ProjectManager getProjectManager() {
		return projectManager;
	}

	/**
	 * Methode d'affectation pour le champ projectManager.
	 * 
	 * @param projectManager la nouvelle valeur du champ a affecter.
	 */
	public void setProjectManager(ProjectManager projectManager) {
		this.projectManager = projectManager;
	}

	/**
	 * Methode d'acces au champ versionManager.
	 * 
	 * @return la valeur du champ versionManager.
	 */
	public VersionManager getVersionManager() {
		return versionManager;
	}

	/**
	 * Methode d'affectation pour le champ versionManager.
	 * 
	 * @param versionManager la nouvelle valeur du champ a affecter.
	 */
	public void setVersionManager(VersionManager versionManager) {
		this.versionManager = versionManager;
	}
}